package com.powernode.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.constant.BusinessEnum;
import com.powernode.domain.Basket;
import com.powernode.domain.Sku;
import com.powernode.ex.handler.BusinessException;
import com.powernode.feign.CartProdFeign;
import com.powernode.mapper.BasketMapper;
import com.powernode.model.CartItem;
import com.powernode.model.Result;
import com.powernode.model.ShopCart;
import com.powernode.service.BasketService;
import com.powernode.utils.AuthUtils;
import com.powernode.vo.CartTotalAmount;
import com.powernode.vo.CartVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class BasketServiceImpl extends ServiceImpl<BasketMapper, Basket> implements BasketService {
    @Autowired
    BasketMapper basketMapper;

    @Autowired
    CartProdFeign cartProdFeign;

    /**
     * 查询指定用户的购物车商品数量
     *
     * @param openId 用户唯一标识
     * @return 购物车商品数量
     */
    @Override
// 定义一个方法用于查询指定用户的购物篮中商品的总数量
    public Integer queryMemberBasketProdCount(String openId) {
        // 使用basketMapper执行一个查询，该查询使用QueryWrapper构建
        // select("ifnull(sum(prod_count),0)")表示选择商品数量的总和，如果总和为null则返回0
        // eq("open_id", openId)表示查询条件是open_id字段等于传入的openId参数
        List<Object> objs = basketMapper.selectObjs(new QueryWrapper<Basket>().select("ifnull(sum(prod_count),0)").eq("open_id", openId));

        // 从查询结果列表中获取第一个元素，因为查询结果应该只有一个值，即商品数量总和
        Object o = objs.get(0);

        // 将查询到的对象转换为字符串，然后再转换为Integer类型，并返回
        // 这里假设查询结果不为空，且可以安全地转换为Integer
        return Integer.valueOf(o.toString());
    }

    /**
     * 查询当前用户的购物车信息
     *
     * @return CartVo 包含当前用户的购物车信息
     * @throws BusinessException 如果远程调用失败，抛出业务异常
     */
    @Override
    public CartVo queryMemberCartVo(String openId) {
        // 创建购物车对象
        CartVo cartVo = new CartVo();
        // 根据会员openId查询购物车记录
        List<Basket> basketList = basketMapper.selectList(new LambdaQueryWrapper<Basket>().eq(Basket::getOpenId, openId));
        // 判断是否有值
        if (CollectionUtils.isEmpty(basketList) || basketList.size() == 0) {
            return cartVo;
        }
        // 从购物车记录集合中获取商品skuId集合
        List<Long> skuIdList = basketList.stream().map(Basket::getSkuId).collect(Collectors.toList());
        // 远程接口调用：根据商品skuId集合查询商品sku对象集合
        Result<List<Sku>> result = cartProdFeign.getSkuListBySkuIds(skuIdList);
        if (BusinessEnum.OPERATION_FAIL.getCode().equals(result.getCode())) {
            throw new BusinessException("远程调用失败：根据商品skuId集合查询商品sku对象集合");
        }
        // 获取数据
        List<Sku> skuList = result.getData();
        // 创建购物车店铺对象集合
        List<ShopCart> shopCartList = new ArrayList<>();
        // 循环遍历购物车记录
        basketList.forEach(basket -> {
            Long shopId = basket.getShopId();
            Long basketId = basket.getBasketId();
            Integer prodCount = basket.getProdCount();

            // 判断当前购物车记录所属店铺是否在购物车店铺对象集合中存在
            List<ShopCart> oneShopCart = shopCartList.stream().filter(shopCart -> shopCart.getShopId().equals(shopId)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(oneShopCart) || oneShopCart.size() == 0) {
                // oneShopCart集合为空：说明当前购物车记录所属店铺在集合中不存在
                // 创建购物车店铺对象
                ShopCart shopCart = new ShopCart();
                // 创建购物车商品条目对象集合
                List<CartItem> cartItemList = new ArrayList<>();
                // 创建购物车商品条目对象
                CartItem cartItem = new CartItem();
                cartItem.setBasketId(basketId);
                cartItem.setProdCount(prodCount);
                // 从商品sku对象集合中过滤出与当前购物车记录中的商品skuId一致的商品对象
                Sku sku1 = skuList.stream().filter(sku -> sku.getSkuId().equals(basket.getSkuId())).collect(Collectors.toList()).get(0);
                // 将商品sku1对象的属性值copy到购物车商品条目对象中
                BeanUtils.copyProperties(sku1, cartItem);

                cartItemList.add(cartItem);
                shopCart.setShopId(shopId);
                shopCart.setShopCartItems(cartItemList);
                shopCartList.add(shopCart);
            } else {
                // oneShopCart集合不为空：说明当前购物车记录所属店铺在集合中存在
                ShopCart shopCart = oneShopCart.get(0);
                List<CartItem> shopCartItems = shopCart.getShopCartItems();

                // 创建购物车商品条目对象
                CartItem cartItem = new CartItem();
                cartItem.setBasketId(basketId);
                cartItem.setProdCount(prodCount);
                // 从商品sku对象集合中过滤出与当前购物车记录中的商品skuId一致的商品对象
                Sku sku1 = skuList.stream().filter(sku -> sku.getSkuId().equals(basket.getSkuId())).collect(Collectors.toList()).get(0);
                // 将商品sku1对象的属性值copy到购物车商品条目对象中
                BeanUtils.copyProperties(sku1, cartItem);
                shopCartItems.add(cartItem);
            }
        });

        cartVo.setShopCarts(shopCartList);
        return cartVo;
    }

    /**
     * 计算会员已勾选的购物车商品总金额
     *
     * @param basketIds 已勾选购物车商品的ID列表
     * @return CartTotalAmount 包括商品总金额、运费、最终金额的对象
     */
    @Override
    public CartTotalAmount calculateMemberCheckedBasketTotalAmount(List<Long> basketIdList) {
        CartTotalAmount cartTotalAmount = new CartTotalAmount();
        // 判断购物车id集合是否有值
        if (CollectionUtils.isEmpty(basketIdList) || basketIdList.size() == 0) {
            return cartTotalAmount;
        }
        // 根据购物车id集合查询购物车记录
        List<Basket> basketList = basketMapper.selectBatchIds(basketIdList);
        // 从购物车记录集合中获取商品skuId集合
        List<Long> skuIdList = basketList.stream().map(Basket::getSkuId).collect(Collectors.toList());
        // 远程调用：根据商品skuId集合查询商品sku对象集合
        Result<List<Sku>> result = cartProdFeign.getSkuListBySkuIds(skuIdList);
        if (BusinessEnum.OPERATION_FAIL.getCode().equals(result.getCode())) {
            throw new BusinessException("远程调用失败，根据商品skuId集合查询商品sku对象集合");
        }
        // 获取数据
        List<Sku> skuList = result.getData();
        // 所有单个商品总金额集合
        List<BigDecimal> oneSkuTotalAmounts = new ArrayList<>();
        // 循环遍历购物车记录
        basketList.forEach(basket -> {
            // 从商品sku对象集合中过滤出与当前购物车记录中skuId一致的商品sku对象
            Sku sku1 = skuList.stream().filter(sku -> sku.getSkuId().equals(basket.getSkuId())).collect(Collectors.toList()).get(0);
            // 计算单个商品总金额
            BigDecimal oneSkuTotalAmount = sku1.getPrice().multiply(new BigDecimal(basket.getProdCount()));
            oneSkuTotalAmounts.add(oneSkuTotalAmount);
        });
        // 计算所有商品总金额
        BigDecimal allSkuTotalAmount = oneSkuTotalAmounts.stream().reduce(BigDecimal::add).get();

        cartTotalAmount.setTotalMoney(allSkuTotalAmount);
        cartTotalAmount.setFinalMoney(allSkuTotalAmount);
        // 计算运费，如果商品总额超过99元免运费，否则运费9元
        if (allSkuTotalAmount.compareTo(new BigDecimal(99)) == -1) {
            cartTotalAmount.setTransMoney(new BigDecimal(9));
            cartTotalAmount.setFinalMoney(allSkuTotalAmount.add(new BigDecimal(9)));
        }
        return cartTotalAmount;
    }

    /**
     * 修改购物车中的商品项
     *
     * 如果购物车中已存在指定商品，则更新商品的数量；
     * 如果购物车中不存在该商品，则添加新商品项。
     *
     * @param basket 包含商品信息的购物车对象
     * @return Boolean 操作是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)// 开启事务，并在发生异常时回滚
    public Boolean changeCartItem(Basket basket) {
        // 获取当前会员的 OpenId
        String openId = AuthUtils.getMemberOpenId();

        // 查询当前用户购物车中是否已有该商品
        Basket beforeBasket = basketMapper.selectOne(
                new LambdaQueryWrapper<Basket>()
                        .eq(Basket::getOpenId, openId) // 根据用户 OpenId 查询
                        .eq(Basket::getSkuId, basket.getSkuId()) // 根据 SKU ID 查询
        );

        // 如果购物车中已存在该商品，则更新商品数量
        if (ObjectUtil.isNotNull(beforeBasket)) {
            // 计算更新后的商品数量
            int finalCount = beforeBasket.getProdCount() + basket.getProdCount();
            // 设置更新后的商品数量
            beforeBasket.setProdCount(finalCount);
            // 更新数据库记录，返回操作结果
            return basketMapper.updateById(beforeBasket) > 0;
        }

        // 如果购物车中不存在该商品，则添加新的商品项
        basket.setCreateTime(new Date()); // 设置创建时间
        basket.setOpenId(openId); // 设置当前用户的 OpenId
        // 插入新商品项，返回操作结果
        return basketMapper.insert(basket) > 0;
    }

}